﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text.RegularExpressions;
using RegexLib.Web.Models.Web;
using RegexLib.Web.Models.Data;
using System.Text;

namespace RegexLib.Web.Controllers
{
	public class RegexController : Controller
	{
		/// <summary>
		/// 查看所有正则表达式。
		/// </summary>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <returns></returns>
		public ActionResult All(int pageIndex, int pageSize)
		{
			using (RxDataContext db = new RxDataContext())
			{
				int count = db.RegexInfos.Count();
				int totalPages = (count + pageSize - 1) / pageSize;
				pageIndex = pageIndex > 0 ? pageIndex : totalPages;

				ViewData["Regexes"] = db.RegexInfos.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToArray();
				ViewData["PageIndex"] = pageIndex;
				ViewData["PageSize"] = pageSize;
				ViewData["TotalPages"] = totalPages;

				return View();
			}
		}

		/// <summary>
		/// 访问正则表达式测试页。
		/// </summary>
		/// <returns></returns>
		public ActionResult Test()
		{
			RegexInfo regex = null;

			try
			{
				string sid = Request["id"];
				Guid id = new Guid(sid);
				regex = RxLibrary.GetRegexById(id);
			}
			catch { }

			ViewData["Regex"] = regex;
			return View();
		}

		/// <summary>
		/// 提交测试数据。
		/// </summary>
		/// <param name="patternString">模式串。</param>
		/// <param name="testString">待匹配的字符串。</param>
		/// <param name="testOption">正则表达式选项。</param>
		/// <returns></returns>
		public ActionResult TestSubmit(string patternString, string testString, RegexOptions testOption)
		{
			if (patternString == null)
				return Json(new { IsError = true, Message = "模式串不能为空。" });

			if (testString == null)
				return Json(new { IsError = true, Message = "待测字符串不能为空。" });

			Regex rx = null;
			try
			{
				rx = new Regex(patternString, testOption);
			}
			catch (ArgumentOutOfRangeException)
			{
				return Json(new { IsError = true, Message = "正则表达式选项有误。" });
			}
			catch (ArgumentException ex)
			{
				return Json(new { IsError = true, Message = "正则表达式模式串错误：" + ex.Message });
			}

			var matches = RxTester.GetMatches(rx, testString);

			return Json(new { IsError = false, Matches = matches, Source = testString });
		}

		/// <summary>
		/// 访问添加正则表达式的页面。
		/// </summary>
		/// <returns></returns>
		public ActionResult Add()
		{
			if (!RxMembership.IsUserLoggedIn())
				return Redirect("/Member/Login/?ReturnUrl=" + HttpUtility.UrlEncode(Request.Url.ToString()));

			return View();
		}

		/// <summary>
		/// 提交添加的正则表达式。
		/// </summary>
		/// <param name="title">标题。</param>
		/// <param name="description">说明。</param>
		/// <param name="pattern">模式串。</param>
		/// <param name="accessKey">访问路径。</param>
		/// <param name="keywords">关键字。</param>
		/// <returns></returns>
		public ActionResult AddSubmit(string title, string description, string pattern, string accessKey, string keywords)
		{
			if (!RxMembership.IsUserLoggedIn())
				return Redirect("/Home/");

			string rawTitle = "";
			if (title == null || (rawTitle = title.Trim()) == "")
				return Json(new { IsError = true, Message = "请填写标题。" });

			string rawDescription = "";
			if (description == null || (rawDescription = description.Trim()) == "")
				return Json(new { IsError = true, Message = "请填写说明。" });

			string rawPattern = "";
			if (pattern == null || (rawPattern = pattern.Trim()) == "")
				return Json(new { IsError = true, Message = "请填写正则表达式模式。" });

			if (!string.IsNullOrEmpty(accessKey) && !accessKey.IsAccessKey())
				return Json(new { IsError = true, Message = "访问路径格式不正确。" });

			if (rawDescription.Length > 1000)
				return Json(new { IsError = true, Message = "说明字数过多，请控制在1000字之内。" });

			try
			{
				new Regex(rawPattern);
			}
			catch(ArgumentException ex)
			{
				return Json(new { IsError = true, Message = "正则表达式格式不正确：" + HttpUtility.HtmlEncode(ex.Message) });
			}

			try
			{
				UserInfo user = RxMembership.GetCurrentUser();

				string[] ks = null;
				if (!string.IsNullOrEmpty(keywords))
				{
					ks = keywords.Split(new char[] { ',', '，', ';', '；' }, StringSplitOptions.RemoveEmptyEntries);
					ks = ks.TrimAndRemoveEmpty();

					if (ks.Where(s => s.Length > 50).Count() > 0)
						return Json(new { IsError = true, Message = "某些关键字过长，请都控制在50字之内。" });
				}

				var regex = RxLibrary.AddRegex(user, rawTitle, accessKey, rawDescription, rawPattern, ks, Request.UserHostAddress);

				return Json(new { IsError = false, Message = RxUrl.GetViewRegexUrl(regex.AccessKey) });
			}
			catch (RxRegexAccessKeyExistsException)
			{
				return Json(new { IsError = true, Message = "指定的访问路径已被使用，请换一个。" });
			}
			catch
			{
				return Json(new { IsError = true, Message = "在添加正则表达式时发生了未知错误，请稍后再试。" });
			}
		}

		/// <summary>
		/// 访问正则表达式详细信息查看页。
		/// </summary>
		/// <param name="accessKey">访问路径。</param>
		/// <returns></returns>
		public ActionResult ViewRegex(string accessKey)
		{
			UserInfo user = RxMembership.GetCurrentUser();
			UserRegex rx = null;
			RegexUserKeyword[] authorKeywords = null;
			RegexUserKeyword[] userKeywords = null;

			using (RxDataContext db = new RxDataContext())
			{
				rx = db.UserRegexes.FirstOrDefault(r => r.RegexAccessKey == accessKey.ToLower());

				if (rx == null)
					return Redirect("/Home/");

				authorKeywords = db.RegexUserKeywords
						.Where(ruk => ruk.RegexId == rx.RegexId && ruk.UserId == rx.UserId)
						.OrderBy(ruk => ruk.Text)
						.ToArray();

				if (user != null && user.UserId != rx.UserId)
				// 未登录用户不显示用户关键字，
				// 已登录用户如果是该正则表达式的作者，也无需单独显示用户关键字
				{
					userKeywords = db.RegexUserKeywords
						.Where(ruk => ruk.RegexId == rx.RegexId && ruk.UserId == user.UserId)
						.OrderBy(ruk => ruk.Text)
						.ToArray();
				}
			}

			string visitor;
			if (user == null)
				visitor = "anonymous";
			else if (user.UserId == rx.UserId)
				visitor = "author";
			else
				visitor = "user";

			StringBuilder sbKeywords = new StringBuilder();
			if (authorKeywords != null)
			{
				foreach (var kw in authorKeywords)
				{
					sbKeywords.Append(kw.Text);
					sbKeywords.Append(' ');
				}
			}
			if (userKeywords != null)
			{
				foreach (var kw in userKeywords)
				{
					sbKeywords.Append(kw.Text);
					sbKeywords.Append(' ');
				}
			}
			sbKeywords.Append(RxSeoUtility.GetMetaKeywords());

			StringBuilder sbDescription = new StringBuilder();
			sbDescription.Append(rx.Description);
			sbDescription.Append(RxSeoUtility.GetMetaDescription());

			ViewData["MetaKeywords"] = sbKeywords.ToString();
			ViewData["MetaDescription"] = sbDescription.ToString();
			ViewData["Visitor"] = visitor;
			ViewData["Regex"] = rx;
			ViewData["AuthorKeywords"] = authorKeywords;
			ViewData["UserKeywords"] = userKeywords;

			return View();
		}

		/// <summary>
		/// 提交针对正则表达式的评论。
		/// </summary>
		/// <param name="regexId">正则表达式ID。</param>
		/// <param name="commentBody">评论内容。</param>
		/// <returns></returns>
		public ActionResult CommentSubmit(Guid regexId, string commentBody)
		{
			try
			{
				RxIPRecorder.CheckIPPolicy(Request.UserHostAddress, RxIPRecordType.MakeComment);
			}
			catch (RxIPPausedException)
			{
				return Json(new { IsError = true, Message = "您发表评论过于频繁，IP地址已被限制。" });
			}
			catch (RxIPBlockedException)
			{
				return Json(new { IsError = true, Message = "您的IP地址已被屏蔽，无法发表评论。" });
			}

			UserInfo user = RxMembership.GetCurrentUser();

			if (user == null)
				return Json(new { IsError = true, Message = "登录超时时间已过，请重新登录。" });

			RegexInfo regex = RxLibrary.GetRegexById(regexId);
			if (regex == null)
				return Json(new { IsError = true, Message = "访问的正则表达式不存在。" });

			string rawBody = "";

			if (commentBody == null || (rawBody = commentBody.Trim()) == "")
				return Json(new { IsError = true, Message = "请输入评论内容。" });

			try
			{
				RxLibrary.AddComment(user, regex, rawBody, Request.UserHostAddress);
				RxIPRecorder.RecordIP(Request.UserHostAddress, RxIPRecordType.MakeComment);
				return Json(new { IsError = false, Message = "评论发表成功，谢谢！" });
			}
			catch
			{
				return Json(new { IsError = true, Message = "在发表评论时遇到错误，请稍后再试。" });
			}
		}

		/// <summary>
		/// 获取针对正则表达式的评论。
		/// </summary>
		/// <param name="regexId">正则表达式。</param>
		/// <param name="pageIndex">获取第几页。</param>
		/// <param name="pageSize">每页几条。</param>
		/// <returns></returns>
		public ActionResult GetComments(Guid regexId, int pageIndex, int pageSize)
		{
			try
			{
				using (RxDataContext db = new RxDataContext())
				{
					var q = db.UserComments
						.Where(uc => uc.RegexId == regexId)
						.OrderBy(uc => uc.AddedTime);

					int totalPages = (q.Count() + pageSize - 1) / pageSize;
					if (pageIndex < 0) pageIndex = totalPages;
					var comments = q.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToArray();

					return Json(new
					{
						IsError = false,
						PageIndex = pageIndex > 0 ? pageIndex : totalPages,
						PageSize = pageSize,
						TotalPages = totalPages,
						Comments = comments.Select(uc => new
						{
							CommentId = uc.CommentId,
							CommentBody = uc.Body,
							CommentAddedTime = uc.AddedTime.ToString("yyyy-MM-dd HH:mm:ss"),
							UserNickname = HttpUtility.HtmlEncode(uc.Nickname),
							UserAccessKey = uc.UserAccessKey,
						}),
					});
				}
			}
			catch (Exception ex)
			{
				return Json(new { IsError = true, Message = "读取评论时发生错误，请稍后再试。" + ex.Message });
			}
		}

		/// <summary>
		/// 访问最新评论页面。
		/// </summary>
		/// <returns></returns>
		public ActionResult LastComments()
		{
			ViewData["LastComments"] = RxLibrary.GetLastComments(-1);
			return View();
		}

		/// <summary>
		/// 针对指定的正则表达式，为当前登录用户添加关键字。
		/// </summary>
		/// <param name="regexId"></param>
		/// <param name="keywords"></param>
		/// <returns></returns>
		public ActionResult AddKeywords(Guid regexId, string keywords)
		{
			UserInfo user = RxMembership.GetCurrentUser();

			if (user == null)
				return Json(new { IsError = true, Message = "登录时间已过，请重新登录。" });

			RegexInfo regex = RxLibrary.GetRegexById(regexId);

			if (regex == null)
				return Json(new { IsError = true, Message = "正则表达式不存在。" });

			if (keywords == null)
				return Json(new { IsError = true, Message = "必须填写关键字。" });

			string[] ks = keywords.Split(new[] { ',', '，', ';', '；' });
			ks = ks.TrimAndRemoveEmpty();
			if (ks.Where(s => s.Length > 50).Count() > 0)
				return Json(new { IsError = true, Message = "某些关键字过长，请都控制在50字之内。" });

			regex.AddKeyword(user, ks);

			return Json(new { IsError = false, Message = "添加成功。" });
		}

		/// <summary>
		/// 针对指定的正则表达式，获取当前用户为其添加的关键字。
		/// </summary>
		/// <param name="regexId"></param>
		/// <returns></returns>
		public ActionResult GetKeywords(Guid regexId)
		{
			UserInfo user = RxMembership.GetCurrentUser();

			if (user == null)
				return Json(new { IsError = true, Message = "登录时间已过，请重新登录。" });

			RegexInfo regex = RxLibrary.GetRegexById(regexId);

			if (regex == null)
				return Json(new { IsError = true, Message = "正则表达式不存在。" });

			var keywords = regex.GetCutomerKeywords(user);

			return Json(new
			{
				IsError = false,
				Keywords = keywords.Select(k => new
				{
					Id = k.KeywordId,
					Text = HttpUtility.HtmlEncode(k.Text),
				})
			});
		}

		/// <summary>
		/// 针对指定的正则表达式，为当前登录用户删除关键字。
		/// </summary>
		/// <param name="regexId"></param>
		/// <param name="keywordId"></param>
		/// <returns></returns>
		public ActionResult DeleteKeyword(Guid regexId, Guid keywordId)
		{
			UserInfo user = RxMembership.GetCurrentUser();

			if (user == null)
				return Json(new { IsError = true, Message = "登录已超时，请重新登录。" });

			try
			{
				RxLibrary.RemoveKeyword(regexId, keywordId, user.UserId);
				return Json(new { IsError = false, Message = "删除成功。" });
			}
			catch
			{
				return Json(new { IsError = true, Message = "发生了未知错误。" });
			}
		}

		/// <summary>
		/// 访问编辑正则表达式的页面。
		/// </summary>
		/// <param name="regexId"></param>
		/// <returns></returns>
		public ActionResult Edit(Guid regexId)
		{
			RegexInfo regex = RxLibrary.GetRegexById(regexId);
			if (regex == null)
				return Redirect("/Home/");

			UserInfo user = RxMembership.GetCurrentUser();
			if (user == null)
				return Redirect("/Home/");

			if (user.UserId != regex.UserId)
				return Redirect("/Home/");

			return View(regex);
		}

		/// <summary>
		/// 提交编辑过的正则表达式。
		/// </summary>
		/// <param name="regexId"></param>
		/// <param name="title"></param>
		/// <param name="description"></param>
		/// <param name="pattern"></param>
		/// <returns></returns>
		public ActionResult EditSubmit(Guid regexId, string title, string description, string pattern)
		{
			UserInfo user = RxMembership.GetCurrentUser();
			if (user == null)
				return Json(new { IsError = true, Message = "登录超时时间已过，请重新登录。" });

			RegexInfo regex = RxLibrary.GetRegexById(regexId);
			if (regex == null)
				return Json(new { IsError = true, Message = "指定的正则表达式不存在。" });

			if (user.UserId != regex.UserId)
				return Json(new { IsError = true, Message = "您不是该正则表达式的发布者。" });

			string rawTitle = "";
			if (title == null || (rawTitle = title.Trim()) == "")
				return Json(new { IsError = true, Message = "请填写标题。" });

			string rawDescription = "";
			if (description == null || (rawDescription = description.Trim()) == "")
				return Json(new { IsError = true, Message = "请填写说明。" });

			string rawPattern = "";
			if (pattern == null || (rawPattern = pattern.Trim()) == "")
				return Json(new { IsError = true, Message = "请填写正则表达式模式。" });

			if (rawDescription.Length > 1000)
				return Json(new { IsError = true, Message = "说明字数过多，请控制在1000字之内。" });

			try
			{
				new Regex(rawPattern);
			}
			catch (ArgumentException ex)
			{
				return Json(new { IsError = true, Message = "正则表达式格式不正确：" + HttpUtility.HtmlEncode(ex.Message) });
			}

			try
			{
				RxLibrary.EditRegex(regexId, rawTitle, rawPattern, rawDescription);
				return Json(new { IsError = false, Message = RxUrl.GetViewRegexUrl(regex.AccessKey) });
			}
			catch
			{
				return Json(new { IsError = true, Message = "发生了未知错误，请稍后再试。" });
			}
		}
	}
}
